package com.i9he.ping.service.impl;

import static com.i9he.ping.utils.ConfigUtils.configuration;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

import com.i9he.ping.model.IPStatus;
import com.i9he.ping.service.IPStrategyHandler;
import com.i9he.ping.utils.JavaMail;
import com.i9he.ping.utils.SmsUtils;

public class MailThread extends Thread implements IPStrategyHandler {
	private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");

	public MailThread() {
		this.brokenMap = new Hashtable<String, IPStatus>();
		this.reconnectList = new ArrayList<IPStatus>();
		this.delayMap = new Hashtable<String, IPStatus>();
	}

	private Map<String, IPStatus> brokenMap; //中断
	private List<IPStatus> reconnectList; //重连
	private Map<String,IPStatus> delayMap; //延迟
	private long preSendTotalTime;

	@Override
	public void run() {
		preSendTotalTime = System.currentTimeMillis() / 1000 / 60;
		while (true) {
			int interval = configuration.getInt("mail.send.new.interval", 60); // 默认60秒
			int totalInterval = configuration.getInt("mail.send.total.interval", 60);// 默认60分钟

			List<IPStatus> brokenIPList = new ArrayList<IPStatus>();
			for (String ip : brokenMap.keySet()) {
				IPStatus status = brokenMap.get(ip);
				if (status != null && Boolean.FALSE.equals(status.getTag())) {
					brokenIPList.add(status);
					status.setTag(Boolean.TRUE);
				}
			}
			List<IPStatus> delayIPList = new ArrayList<>();
			for(String ip :delayMap.keySet()){
				IPStatus IPs = delayMap.get(ip);
				if(IPs != null){
					delayIPList.add(IPs);
				}
			}
			
			//发送网络延迟告警邮件
			this.sendDelay(delayIPList);
			// 发送新中断邮件
			this.sendBroken(brokenIPList);
			// 发送中断短信
			this.sendSms(brokenIPList);

			// 发送重连邮件
			this.sendReconnect(reconnectList);
			reconnectList.clear();

			// 发送汇总邮件
			long currentTime = System.currentTimeMillis() / 1000 / 60;
			if (preSendTotalTime + totalInterval < currentTime) {
				this.sendBroken(new ArrayList<IPStatus>(brokenMap.values()));
				preSendTotalTime = currentTime;
			}

			try {
				Thread.sleep(interval * 1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	private void sendBroken(List<IPStatus> brokenIPList) {
		Map<String, Object> models = new HashMap<String, Object>();
		models.put("datetime", dateFormat.format(new Date()));
		String[] groups = configuration.getStringArray("ip.group");
		for (String grp : groups) {
			List<String> groupList = Arrays.asList(configuration.getString("ip.group." + grp, "").split(";"));
			List<Object> receivers = configuration.getList("ip.mail." + grp);

			List<String> results = new ArrayList<String>();
			for (IPStatus status : brokenIPList) {
				if (!groupList.contains(status.getIp())) {
					continue;
				}
				results.add(status.getBrokenText());
			}
			String subject = "九河互联 - 服务器IP中断  - " + configuration.getString("ip.mail." + grp + ".subject", "");
			if (CollectionUtils.isNotEmpty(results)) {
				models.put("iplist", StringUtils.join(results, "\n"));
				sendMail("broken.html", subject, receivers, models);
			}

		}
	}
	
	private void sendDelay(List<IPStatus> delayIPList){
		Map<String, Object> models = new HashMap<String, Object>();
		models.put("datetime", dateFormat.format(new Date()));
		String[] groups = configuration.getStringArray("ip.group");
		for (String grp : groups) {
			List<String> groupList = Arrays.asList(configuration.getString("ip.group." + grp, "").split(";"));
			List<Object> receivers = configuration.getList("ip.mail." + grp);

			List<String> results = new ArrayList<String>();
			for (IPStatus status : delayIPList) {
				if (!groupList.contains(status.getIp())) {
					continue;
				}
				results.add(status.getDelayText());
			}
			String subject = "九河互联 - 服务器I网络延迟  - " + configuration.getString("ip.mail." + grp + ".subject", "");
			if (CollectionUtils.isNotEmpty(results)) {
				System.out.println(results.size() + "------------------------------------------");
				models.put("iplist", StringUtils.join(results, "\n"));
				sendMail("delay.html", subject, receivers, models);
			}

		}
	}
	
	
	private void sendSms(List<IPStatus> brokenIPList) {
		String[] groups = configuration.getStringArray("ip.group");
		for (String grp : groups) {
			List<String> groupList = Arrays.asList(configuration.getString("ip.group." + grp, "").split(";"));

			List<String> iplist = new ArrayList<String>();
			for (IPStatus status : brokenIPList) {
				if (!groupList.contains(status.getIp())) {
					continue;
				}
				iplist.add(status.getIp());
			}

			// 发送短信通知
			String[] phones = configuration.getStringArray("ip.sms." + grp);
			if (phones != null && phones.length > 0 && iplist.size() > 0) {
				SmsUtils.sendBreakIp(phones, iplist.toArray(new String[0]));
			}
		}
	}

	private void sendReconnect(List<IPStatus> brokenIPList) {
		Map<String, Object> models = new HashMap<String, Object>();
		models.put("datetime", dateFormat.format(new Date()));
		String[] groups = configuration.getStringArray("ip.group");
		for (String grp : groups) {
			List<String> groupList = Arrays.asList(configuration.getString("ip.group." + grp, "").split(";"));

			List<Object> receivers = configuration.getList("ip.mail." + grp);

			List<String> results = new ArrayList<>();
			for (IPStatus status : brokenIPList) {
				if (!groupList.contains(status.getIp())) {
					continue;
				}
				results.add(status.getReconnectText());
			}
			String subject = "九河互联-服务器IP恢复  - " + configuration.getString("ip.mail." + grp + ".subject", "");
			if (CollectionUtils.isNotEmpty(results)) {
				models.put("iplist", StringUtils.join(results, "\n"));
				sendMail("reconnect.html", subject, receivers, models);
			}
		}
	}

	private void sendMail(String file, String subject, List receivers, Map<String, Object> models) {
		String html = "";
		try (InputStream stream = MailThread.class.getClassLoader().getResourceAsStream(file)) {
			html = IOUtils.toString(stream, "utf-8");
			if (models != null) {
				for (String key : models.keySet()) {
					html = StringUtils.replace(html, "{" + key + "}", String.valueOf(models.get(key)));
				}
			}
			stream.close();
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
		for (Object receiver : receivers) {
			final String url = configuration.getString("mail.server");
			new JavaMail(true).doSendHtmlEmail(subject, html, receiver.toString());
		}
	}

	@Override
	public void broken(IPStatus ip) {
		if (!brokenMap.containsKey(ip.getIp())) {
			ip.setTag(Boolean.FALSE);
			brokenMap.put(ip.getIp(), ip);
		}
		reconnectList.remove(ip);
	}

	@Override
	public void reconnect(IPStatus ip) {
		brokenMap.remove(ip.getIp());
		reconnectList.add(ip);
	}

	@Override
	public void delay(IPStatus ip) {
		if(!delayMap.containsKey(ip.getIp()))
			delayMap.put(ip.getIp(), ip);
		brokenMap.remove(ip.getIp());
		reconnectList.remove(ip);
	}

}
